package com.ybg.share.config.mybatis;

import com.alibaba.druid.pool.DruidDataSource;
import com.ybg.share.config.SystemInit;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.InlineShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;


/**
 * 数据库分表配置
 */
@Configuration
@Slf4j
public class DbConfiguration {

    /**
     * 单库分表
     *
     * @return
     */
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.driver-class-name",havingValue = "com.mysql.cj.jdbc.Driver")
    public DataSource dataSource(@Value("${sharding.spring.datasource.url}") String url,
                                 @Value("${sharding.spring.datasource.username}") String username,
                                 @Value("${sharding.spring.datasource.password}") String password, @Value("${sql.show}") String showSQL,
                                 @Value("${spring.datasource.driver-class-name}" )String driverClassName
    ) {
        log.info("使用自定义配置 DataSource");
       //https://blog.csdn.net/yzh_1346983557/article/details/88547234
        DruidDataSource db = new DruidDataSource();
        db.setUrl(url);
        db.setUsername(username);
        db.setPassword(password);
        db.setDriverClassName(driverClassName);
//        db.setMaxActive(200);
        db.setMinIdle(3000);
        db.setMaxActive(4000);
//        db.setMaxWait(8000);
     //   db.setMinEvictableIdleTimeMillis(3000);
        db.setPoolPreparedStatements(true);
      //  db.setMaxOpenPreparedStatements(250);
        db.setValidationQuery("SELECT 1");
        //指明连接是否被空闲连接回收器(如果有)进行检验，如果检测失败，则连接将被从池中去除
//        db.setTestWhileIdle(true);
//        //在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位，一般比minEvictableIdleTimeMillis小
//        db.setTimeBetweenEvictionRunsMillis(60000);
        db.setConnectionErrorRetryAttempts(10);
//        db.setRemoveAbandoned(true);
//        db.setRemoveAbandonedTimeout(1000);
//        db.setValidationQueryTimeout(db.getValidationQueryTimeout());
//        //连接池中连接，在时间段内一直空闲，被逐出连接池的时间(1000*60*60)，以毫秒为单位
//        db.setMinEvictableIdleTimeMillis(60*1000);
        db.setTestOnBorrow(true);//申请连接时执行validationQuery检测连接是否有效，做了这个配置会 降低性能。
        db.setTestOnReturn(true);//归还连接时执行validationQuery检测连接是否有效，做了这个配置会降 低性能。

        ArrayList<String> connectionInitSqls = new ArrayList<String>();
        connectionInitSqls.add("set names utf8mb4;");
        db.setConnectionInitSqls(connectionInitSqls);
        // TODO 如果不想支持分表，则直接return db；
        // return db;

        // 华丽的分割线------------------------------------------------------------------------
        // 下面支持分表
        //其他表暂时保持不变
        Collection<TableRuleConfiguration> tableRuleConfigs = new ArrayList<TableRuleConfiguration>();
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
//		shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new NoneShardingStrategyConfiguration());
//		shardingRuleConfig.setDefaultTableShardingStrategyConfig(new NoneShardingStrategyConfiguration());
        Map<String, DataSource> dataSourceMap = new LinkedHashMap<String, DataSource>();
        dataSourceMap.put("ds0", db);

        // 自定义策略，根据公众号app_id分表


        // 日K
        InlineShardingStrategyConfiguration share_stock_day_k_stock_id = new InlineShardingStrategyConfiguration("stock_id", "share_stock_day_k${stock_id % " + SystemInit.SHARE_STOCK_DAYK_TABLESHARDING + "}");
        TableRuleConfiguration share_stock_day_k = new TableRuleConfiguration("share_stock_day_k", "ds0.share_stock_day_k${0.." + (SystemInit.SHARE_STOCK_DAYK_TABLESHARDING - 1) + "}");
        share_stock_day_k.setTableShardingStrategyConfig(share_stock_day_k_stock_id);
        tableRuleConfigs.add(share_stock_day_k);
        // 月度统计
        InlineShardingStrategyConfiguration share_stock_count_month_stock_id = new InlineShardingStrategyConfiguration("stock_id", "share_stock_count_month${stock_id % " + SystemInit.SHARE_STOCK_COUNT_MONTH_TABLESHARDING + "}");
        TableRuleConfiguration share_stock_count_month = new TableRuleConfiguration("share_stock_count_month", "ds0.share_stock_count_month${0.." + (SystemInit.SHARE_STOCK_COUNT_MONTH_TABLESHARDING - 1) + "}");
        share_stock_count_month.setTableShardingStrategyConfig(share_stock_count_month_stock_id);
        tableRuleConfigs.add(share_stock_count_month);


        shardingRuleConfig.setTableRuleConfigs(tableRuleConfigs);
        Properties props = new Properties();
        props.put("sql.show", showSQL);
        try {
            return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, props);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println("配置失败");
        return db;
    }

}
